package com.rainbow.autocode.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.rainbow.autocode.entity.SqlDmlEntity;
import com.rainbow.autocode.service.SysGeneratorService;
import com.rainbow.autocode.utils.PageUtils;
import com.rainbow.autocode.utils.Query;
import com.rainbow.autocode.utils.R;
import com.rainbow.autocode.utils.RRException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 代码生成器
 *
 * @author 付为地
 * @email 1335157415@qq.com
 * @date 2016年12月19日 下午9:12:58
 */
@Slf4j
@Controller
@RequestMapping("/sys/generator")
public class SysGeneratorController {
	@Autowired
	private SysGeneratorService sysGeneratorService;

	@Autowired
	Environment env;

	/*执行sql的脚本目录*/
	@Value("${upload.file.dir}")
	private String fileDir;

	/**
	 * 列表
	 */
	@ResponseBody
	@RequestMapping("/list")
	public R list(@RequestParam Map<String, Object> params){
		//pgsql当前schema
		String currentSchema=getSchema(env.getProperty("spring.datasource.url"));
		params.put("schemaname",currentSchema);
		//查询列表数据
		Query query = new Query(params);
		List<Map<String, Object>> list = sysGeneratorService.queryList(query);
		int total = sysGeneratorService.queryTotal(query);

		PageUtils pageUtil = new PageUtils(list, total, query.getLimit(), query.getPage());

		return R.ok().put("page", pageUtil);
	}

	/**
	 * 生成代码
	 */
	@RequestMapping("/code")
	public void code(HttpServletRequest request, HttpServletResponse response) throws IOException{
		JSONArray tableNames = new JSONArray();
		String tables = request.getParameter("tables");
		//服务拆分之后，控制层和持久化层服务英文名称
		String service = request.getParameter("service");
		String[] serviceArr=new String[]{"com","com.rainbow.mall","user","user","controller","service","dao","entity","false","rainbow","1335157415@qq.com","true","true"};
		SqlDmlEntity dmlEntity=new SqlDmlEntity();
		if(!ObjectUtils.isEmpty(service)){
			serviceArr=service.split(",");
		}
		dmlEntity.setMainPath("com");
		dmlEntity.setPackageName(ObjectUtils.isEmpty(serviceArr[1])?"com.rainbow.mall":serviceArr[1]);
		dmlEntity.setModuleName(ObjectUtils.isEmpty(serviceArr[2])?"user":serviceArr[2]);
		dmlEntity.setBottomName(ObjectUtils.isEmpty(serviceArr[3])?"user":serviceArr[3]);
		dmlEntity.setControllerName(ObjectUtils.isEmpty(serviceArr[4])?"controller":serviceArr[4]);
		dmlEntity.setServiceName(ObjectUtils.isEmpty(serviceArr[5])?"service":serviceArr[5]);
		dmlEntity.setDaoName(ObjectUtils.isEmpty(serviceArr[6])?"dao":serviceArr[6]);
		dmlEntity.setEntityName(ObjectUtils.isEmpty(serviceArr[7])?"entity":serviceArr[7]);
		dmlEntity.setDynamicLikeEnable(ObjectUtils.isEmpty(serviceArr[8])?false:Boolean.parseBoolean(serviceArr[8]));
		dmlEntity.setAuthor(ObjectUtils.isEmpty(serviceArr[9])?"rainbow":serviceArr[9]);
		dmlEntity.setEmail(ObjectUtils.isEmpty(serviceArr[10])?"1335157415@qq.com":serviceArr[10]);
		dmlEntity.setEnableFeignDefault(ObjectUtils.isEmpty(serviceArr[11])?false:Boolean.parseBoolean(serviceArr[11]));
		dmlEntity.setEnableFallBackDefault(ObjectUtils.isEmpty(serviceArr[12])?false:Boolean.parseBoolean(serviceArr[12]));
		//pgsql当前schema
		String currentSchema=getSchema(env.getProperty("spring.datasource.url"));
		dmlEntity.setSchema(currentSchema);
		tableNames = JSON.parseArray(tables);
		byte[] data = sysGeneratorService.generatorCode(tableNames,dmlEntity);

		response.reset();
		response.setHeader("Content-Disposition", "attachment; filename=\"AutoCode.zip\"");
		response.addHeader("Content-Length", "" + data.length);
		response.setContentType("application/octet-stream; charset=UTF-8");

		IOUtils.write(data, response.getOutputStream());
	}

	/**
	 * 创建表
	 */
	@RequestMapping("/save")
	@ResponseBody
	public R save(@RequestBody SqlDmlEntity table) throws ClassNotFoundException, SQLException, IOException {
		Assert.notNull(table,"脚本语句不允许为空!");
		Assert.notNull(table.getTable(),"脚本语句不允许为空!");
		Class.forName(env.getProperty("spring.datasource.driverClassName"));
		Connection conn = DriverManager.getConnection(env.getProperty("spring.datasource.url"), env.getProperty("spring.datasource.username"), env.getProperty("spring.datasource.password"));
		ScriptRunner runner = new ScriptRunner(conn);
		try {
			File file=new File(fileDir+ File.separator+"table.sql");
			FileUtils.writeStringToFile(file,table.getTable(),"UTF-8");
			runner.setStopOnError(true);
			runner.runScript(new InputStreamReader(FileUtils.openInputStream(file),"UTF-8"));
		} catch (Exception exp) {
			throw new RRException(exp.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value());
		}finally {
			conn.close();
		}
		return R.ok();
	}


	/**
	 * 获取当前schema
	 * @param url
	 * @return
	 */
	private String getSchema(String url){
		if(StringUtils.isNotEmpty(url)&&url.indexOf("?")!=-1){
			String[] dataArr=url.split("\\?")[1].split("&");
			if(!ObjectUtils.isEmpty(dataArr)){
				List<String> dataList= Arrays.asList(dataArr);
				Optional<String> schemaOpt=dataList.stream().filter(t->!ObjectUtils.isEmpty(t)&&t.contains("currentSchema=")).findAny();
				if(schemaOpt.isPresent()){
					return schemaOpt.get().replaceAll("currentSchema=","");
				}
			}
		}
		return null;
	}


}
